#include <stdio.h>
#include <ctype.h>
#include<iostream>
#include<math.h>
using namespace std;

///////////////////////////////////////////////////////////////////////////////
//作者：程紫阳
//日期：2016年5月5日
//功能：本计算器可以实现对诸如 3+(1+7)*6+4*((5+4))这样的表达式的计算，仅限于带括号的 +, * 运算
//描述：1 程序实现。每个非终结符对应一个分析函数。2 修改后的文法如下所示，其中 e 代表空串
///////////////////////////////////////////////////////////////////////////////

//E -> TE' 
//E' -> +TE' | e
//T -> FT'
//T' -> *FT' | e
//F -> NUM | (E)
//FIRST(E) = {NUM, LEFTB}
//FIRST(E') = {PLUS, e}
//FIRST(T) = {NUM, LEFTB}
//FIRST(T') = {MULT, e}
//FIRST(F) = {NUM, LEFTB}
//FOLLOW(E) = {$, RIGHTB}
//FOLLOW(E') = {$, RIGHTB}
//FOLLOW(T) = {PLUS, RIGHTB, $}
//FOLLOW(T') = {PLUS, RIGHTB, $}
//FOLLOW(F) = {MULT, PLUS, RIGHTB, $}

enum TOKEN { PLUS, MULT, NUM, END, ERR, LEFTB, RIGHTB };
char lookahead;
enum TOKEN token;
double num;
int error = 0;
FILE *fp;

void lexical(FILE *fp);
int match(enum TOKEN x);
double E();
double E_();
double T();
double T_();
double F();


//return 0 if success, return 1 otherwise
int match(enum TOKEN x) {
	if (token == x) {
		lexical(fp);//接着读取下一个字符 并保存记号 于 token
		return 0;
	}
	else {
		error = 1;
		return 1;
	}
}

//E -> TE' 
double E() {
	switch (token)
	{
	case LEFTB: case NUM:
		return T() + E_();//一旦匹配到E_()就得 加上所匹配的东西
	default:
		error = 1;//报错
		cout << "error E()" << endl;
		break;
	}
	return 0;
}

//E_ -> +TE'|e 
double E_() {
	switch (token)
	{
	case PLUS:
		match(PLUS); return T() + E_();//由于T()后面是E_()所以加上自身
	case RIGHTB: case END:
		return 0;//加上0 和不变
	default:
		error = 1;//报错
		cout <<"error E_()"<< endl;
		break;
	}
	return 0;
}

//T -> FT'
double T() {
	switch (token)
	{
	case LEFTB: case NUM:
		return F()*T_();
	default:
		error = 1;//报错
		cout << "errorT()" << endl;
		break;
	}
	return 0;
}


//T' -> *FT' | e
double T_() {
	switch (token)
	{
	case MULT:
		match(MULT); return F()*T_();
	case PLUS: case RIGHTB: case END:
		return 1;
	default:
		error = 1;//报错
		cout << "error T_()" << endl;
		break;
	}
	return 0;
}

//F -> NUM | (E)
double F() {
	double temp;//用于保存E()的值
	switch (token)
	{
	case LEFTB: 
		match(LEFTB);
		temp = E();
		match(RIGHTB);
		return temp;
	case NUM:
		temp = num;
		match(NUM);
		return temp;
	default:
		error = 1;//报错
		cout << "error F()" << endl;
		break;
	}
	return 0;
}

//读入文本，保存记号流，将记号保存在 token 中，数字 保存在NUM 中
void lexical(FILE *fp) {

	lookahead = getc(fp);
	num = 0;

	while (lookahead == ' ' || lookahead == '\t' || lookahead == '\n') {
		lookahead = getc(fp);
	}
	//这个是整数
	/*if (isdigit(lookahead)) {
		num = 0;
		while (isdigit(lookahead)) {
			token = NUM;
			num = num * 10 + lookahead - '0';//相当于左移一位
			lookahead = getc(fp);
		}
		//测试用cout << num << endl;
		ungetc(lookahead, fp);//回退一步
		return;
	}*/
	//这个是double
	if (isdigit(lookahead)) {
		int count = 0;
		if (isdigit(lookahead) || lookahead == '.'){
			num = 0;
			while (isdigit(lookahead)) {
				token = NUM;
				num = num * 10 + lookahead - '0';//相当于左移一位
				lookahead = getc(fp);
			}
			if (lookahead == '.'){
				lookahead = getc(fp);
				while (isdigit(lookahead)){
					num = num * 10 + lookahead - '0';//相当于左移一位
					lookahead = getc(fp);
					count++;
				}
				num = (num * (pow(0.1,count)));//移动小数点
			}
			ungetc(lookahead, fp);//回退一步
			return;
		}
	}
	else if (lookahead == '+') {
		token = PLUS;
		return;
	}
	else if (lookahead == '*') {
		token = MULT;
		return;
	}
	else if (lookahead == EOF) {
		token = END;
		return;
	}
	else if (lookahead == '(') {
		token = LEFTB;//左括号
		return;
	}
	else if (lookahead == ')') {
		token = RIGHTB;//右括号
		return;
	}
	else {
		error = 1;//有错误
		token = ERR;
		return;
	}
}

int main(int argc, char **argv) {
	double  res = 0.0;
	if (argc < 2) {
		printf("insufficient arguments");
		return 1;
	}
	fp = fopen(argv[1], "r");

	lexical(fp);
	res = E();//输出结果
	if (!error) {
		cout << res << endl;
	}
	else {
		printf("There are errors\n");
	}

	fclose(fp);
	return 0;

}
